//给你一个长度为 n 的链表，每个节点包含一个额外增加的随机指针 random ，该指针可以指向链表中的任何节点或空节点。 
//
// 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成，其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 
//指针也都应指向复制链表中的新节点，并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。 
//
// 例如，如果原链表中有 X 和 Y 两个节点，其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ，同样有 x.random 
//--> y 。 
//
// 返回复制链表的头节点。 
//
// 用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示： 
//
// 
// val：一个表示 Node.val 的整数。 
// random_index：随机指针指向的节点索引（范围从 0 到 n-1）；如果不指向任何节点，则为 null 。 
// 
//
// 你的代码 只 接受原链表的头节点 head 作为传入参数。 
//
// 
//
// 示例 1： 
//
// 
//
// 
//输入：head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
//输出：[[7,null],[13,0],[11,4],[10,2],[1,0]]
// 
//
// 示例 2： 
//
// 
//
// 
//输入：head = [[1,1],[2,1]]
//输出：[[1,1],[2,1]]
// 
//
// 示例 3： 
//
// 
//
// 
//输入：head = [[3,null],[3,0],[3,null]]
//输出：[[3,null],[3,0],[3,null]]
// 
//
// 
//
// 提示： 
//
// 
// 0 <= n <= 1000
// 
// -10⁴ <= Node.val <= 10⁴ 
// Node.random 为 null 或指向链表中的节点。 
// 
//
// 
//
// Related Topics 哈希表 链表 👍 1291 👎 0

  
package com.tyrone.leetcode.editor.cn;



import java.util.HashMap;
import java.util.Map;

public class CopyListWithRandomPointer{
    public static void main(String[] args) {
       Solution solution = new CopyListWithRandomPointer().new Solution();
    }
    //leetcode submit region begin(Prohibit modification and deletion)
/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/

class Solution {
    //一开始想的是直接用个map来存在所有的新建的节点，然后遍历一次原来是的数组。
    // 但是这样的话没有考虑数字可以是重复的 无法判断哪个到底是哪个？
    // 需要解决这个问题！   Map<ListNode,Integer,Integer>

//    public Node copyRandomList(Node head) {
//        Map<Integer,Node> map = new HashMap<>();
//        if (head == null) return null;
//        Node pre = new Node(-1);
//        Node curr = pre;
//        Node temp = head;
//        while (temp != null) {
//            curr = curr.next;  //指针移动下一个
//            Node node = new Node(temp.val);  //新创建一个node
//            map.put(temp.val,node);
//            curr = node;
//            temp = temp.next;  //移动下一个
//        }
//         temp = head;
//
//        while (temp != null) {
//            Node cur = map.get(temp.val);
//            cur.random = temp.random != null ? map.get(temp.random.val) : null;
//            System.out.println(cur.random);
//            cur.next = temp.next != null ? map.get(temp.next.val) : null;
//            System.out.println(cur.next);
//            temp = temp.next;  //移动下一个
//        }
//        return pre.next;
//    }

    /**
     * K : 原先的node V：深拷贝之后的new
     */
    /**
     * 使用递归的方式和哈希表的方式去做，node.next 完了之后 所有的map就给填写完了
     */
    Map<Node,Node> cacheNode = new HashMap<>();
    public Node copyRandomList(Node head) {
        if (head == null) return null;
        if (!cacheNode.containsKey(head)) {
            Node node = new Node(head.val);
            cacheNode.put(head, node);
            node.next = copyRandomList(head.next);
            node.random = copyRandomList(head.random);
        }
        return cacheNode.get(head);
    }
}
//leetcode submit region end(Prohibit modification and deletion)
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
}